home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / btoa52.zip / ATOB.C next >
C/C++ Source or Header  |  1994-04-08  |  10KB  |  403 lines

  1. /* atob.c */
  2.  
  3. /* Written by Paul Rutter, Joe Orost & Stefan Parmark. */
  4.  
  5. #include <stdio.h>
  6. #ifdef AMIGA
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #endif AMIGA
  10.  
  11. #include "btoa.h"
  12. #if USE_MACROS
  13. #include "chksum.h"
  14. #endif USE_MACROS
  15.  
  16.  
  17. BYTE atob(infile)
  18. register FILE *infile;
  19. {
  20.   register BYTE error;
  21.   register LONG filepos;
  22.   int maxperline;
  23.   LONG n1, n2, oeor, osum, orot, lastline;
  24.   static BYTE outfilename[BUFSIZE];
  25.   extern LONG Ceor, Csum, Crot;
  26.   extern FILE *outfile;
  27.   extern BYTE new_version, openoutput, buffer[BUFSIZE];
  28.  
  29.   error = FALSE;
  30.  
  31.   /* Search for archive header. */
  32.   do
  33.   {
  34.     filepos = ftell(infile);
  35.  
  36.     if (readbuffer(buffer, "archive", infile))
  37.       error = TRUE;
  38.   }
  39.   while (!(error || strncmp(buffer, "xbtoa", 5) == 0));
  40.  
  41.   if (!error)
  42.     if (strcmp(buffer, "xbtoa Begin\n") == 0)
  43.     {
  44.       new_version = FALSE;
  45.       fprintf(stderr, "btoa: Old btoa format.\n");
  46.     }
  47.     else if (sscanf(buffer, "xbtoa5 %d %s Begin\n", &maxperline, outfilename) == 2)
  48.     {
  49.       new_version = TRUE;
  50.       /* Naming a file overrides the read-name-from-file function. */
  51.       if (!openoutput && strcmp(outfilename, "-") != 0)
  52.         if ((outfile = fopen_write(outfilename)) == NULL)
  53.           error = TRUE;
  54.         else
  55.           openoutput = TRUE;
  56.     }
  57.     else
  58.     {
  59.       fprintf(stderr, "btoa: Illegal archive header.\n");
  60.       error = TRUE;
  61.     }
  62.  
  63.   if (!error)
  64.   {
  65.     Ceor = Csum = Crot = 0;
  66.  
  67.     if (new_version)
  68.       error = new_decodefile(infile, &lastline, filepos, maxperline);
  69.     else
  70.       error = old_decodefile(infile, &lastline);
  71.   }
  72.  
  73.   if (!error)
  74.   {
  75.     if (sscanf(buffer, "xbtoa End N %ld %lx E %lx S %lx R %lx\n",
  76.         &n1, &n2, &oeor, &osum, &orot) != 5)
  77.     {
  78.       fprintf(stderr, "btoa: Bad format on line %ld. Can't repair file.\n",
  79.           lastline);
  80.       error = TRUE;
  81.     }
  82.     else if ((n1 != n2) || (oeor != Ceor) || (osum != Csum) || (orot != Crot))
  83.     {
  84.       fprintf(stderr, "btoa: Bad file checksum. Can't repair file.\n");
  85.       error = TRUE;
  86.     }
  87.     else
  88.       /* Flush last characters. */
  89.       decode_line(NULL, (int) ((n1 - 1) & 0x03));
  90.   }
  91.  
  92.   return(error);
  93. }
  94.  
  95.  
  96. /* Peek at the next byte without moving the file pointer. */
  97. int nextbyte(infile)
  98. register FILE *infile;
  99. {
  100.   register int ch;
  101.   register LONG filepos;
  102.  
  103.   filepos = ftell(infile);
  104.   ch = fgetc(infile);
  105.   fseek(infile, filepos, 0);
  106.  
  107.   return(ch);
  108. }
  109.  
  110.  
  111. BYTE new_decodefile(infile, lastline, filepos, maxperline)
  112. register FILE *infile;
  113. LONG *lastline, filepos;
  114. int maxperline;
  115. {
  116.   register int length;
  117.   int ch;
  118.   register BYTE stop, error, newerror, errorstart;
  119.   register LONG line, prevfilepos, startpos;
  120.   struct Diagnosis diagnosislist;
  121.   extern LONG Csum;
  122.   extern BYTE buffer[BUFSIZE];
  123.  
  124.   error = FALSE;
  125.  
  126.   line = 1;  /* Current line number. */
  127.  
  128.   /* A sequence of errors is indicated by errorstart. When it */
  129.   /* changes from TRUE to FALSE a diagnosis record will be    */
  130.   /* generated.                                               */
  131.   stop = errorstart = FALSE;
  132.  
  133.   /* File position of the line before the error sequence.     */
  134.   /* That is the last correct line.                           */
  135.   startpos = 0;
  136.  
  137.   while (!stop)
  138.   {
  139.     prevfilepos = filepos;
  140.     filepos = ftell(infile);
  141.  
  142.     /* Newerror indicates an error on the current line. */
  143.     newerror = FALSE;
  144.  
  145.     line++;
  146.     if (readbuffer(buffer, "archive", infile))
  147.       newerror = stop = TRUE;
  148.     else if (buffer[0] == 'x')  /* End of archive found. */
  149.       stop = TRUE;
  150.     else if ((length = strlen(buffer) - 1) != maxperline ||
  151.              buffer[length] != '\n')
  152.     {
  153.       /* If last character wasn't end-of-line, then we */
  154.       /* have to read until it is found.               */
  155.       if (buffer[length] != '\n')
  156.       {
  157.         newerror = TRUE;
  158.         while ((ch = fgetc(infile)) != EOF && (BYTE)ch != '\n')
  159.           ;
  160.         if (ch == EOF)
  161.           stop = TRUE;
  162.       }
  163.       else if (length > maxperline || nextbyte(infile) != 'x')
  164.       {
  165.         newerror = TRUE;
  166.         Csum = DECODE(buffer[length - 1]);  /* Make Csum correct (modulo 85). */
  167.       }
  168.  
  169.       if (newerror)
  170.         fprintf(stderr, "btoa: Bad line length on line %ld.\n", line);
  171.     }
  172.  
  173.     if (!(newerror || stop))
  174.     {
  175.       if (decode_line(buffer, length - 1))
  176.       {
  177.         if (!error)
  178.           fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
  179.         newerror = TRUE;
  180.       }
  181.  
  182.       /* Examine checksum. */
  183.       if ((ch = buffer[length - 1]) == ENCODE(Csum % 85))
  184.       {
  185.         if (errorstart)
  186.         {
  187.           intodiagnosislist(&diagnosislist, startpos, filepos);
  188.           errorstart = FALSE;
  189.         }
  190.       }
  191.       else
  192.       {
  193.         newerror = TRUE;
  194.         fprintf(stderr, "btoa: Bad checksum on line %ld.\n", line);
  195.         Csum = DECODE(ch);  /* Make Csum correct (modulo 85). */
  196.       }
  197.     }
  198.  
  199.     if (newerror)
  200.     {
  201.       if (!error)
  202.       {
  203.         fprintf(stderr, "btoa: Starting diagnosis.\n");
  204.         diagnosislist.next = diagnosislist.last = NULL;
  205.       }
  206.  
  207.       error = TRUE;
  208.       if (!errorstart)
  209.       {
  210.         errorstart = TRUE;
  211.         startpos = prevfilepos;
  212.       }
  213.     }
  214.   }
  215.  
  216.   if (error)
  217.   {
  218.     if (errorstart)
  219.       intodiagnosislist(&diagnosislist, startpos, filepos);
  220.     producediagnosis(&diagnosislist, infile);
  221.   }
  222.  
  223.   *lastline = line;
  224.  
  225.   return(error);
  226. }
  227.  
  228.  
  229.  
  230. BYTE old_decodefile(infile, lastline)
  231. register FILE *infile;
  232. LONG *lastline;
  233. {
  234.   register int length;
  235.   register BYTE stop, error;
  236.   register LONG line;
  237.   extern BYTE buffer[BUFSIZE];
  238.  
  239.   error = FALSE;
  240.  
  241.   line = 1;
  242.   stop = FALSE;
  243.   while (!stop)
  244.   {
  245.     line ++;
  246.  
  247.     if (readbuffer(buffer, "archive", infile))
  248.       error = stop = TRUE;
  249.     else if (buffer[0] == 'x')  /* End of archive found. */
  250.       stop = TRUE;
  251.     else
  252.     {
  253.       length = strlen(buffer) - 1;
  254.       if (buffer[length] != '\n')
  255.         error = stop = TRUE;  /* The line was longer than the buffer. */
  256.     }
  257.  
  258.     if (!stop)
  259.     {
  260.       if (decode_line(buffer, length))
  261.       {
  262.         fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
  263.         error = stop = TRUE;
  264.       }
  265.     }
  266.   }
  267.  
  268.   *lastline = line;
  269.  
  270.   return(error);
  271. }
  272.  
  273.  
  274. BYTE decode_line(buffer, length)
  275. register BYTE *buffer;
  276. register int length;
  277. {
  278.   register int ch;
  279.   register BYTE error;
  280.   register LONG tmp_codeword;
  281.   extern BYTE new_version;
  282.   extern FILE *outfile;
  283.   static LONG codeword;
  284.   static int ch1, ch2, ch3, ch4;
  285.   static BYTE bytecount = 0;
  286.  
  287.   error = FALSE;
  288.  
  289.   if (buffer == NULL)  /* Flush last characters. */
  290.   {
  291.     if (bytecount > 0)
  292.     {
  293.       fputc(ch1, outfile);
  294.       if (length > 0)
  295.         fputc(ch2, outfile);
  296.       if (length > 1)
  297.         fputc(ch3, outfile);
  298.       if (length > 2)
  299.         fputc(ch4, outfile);
  300.     }
  301.   }
  302.   else
  303.   {
  304.     while (length > 0)
  305.     {
  306.       length--;
  307.       ch = *buffer++;
  308.  
  309.       /* Delayed output. This is to make sure that files with lengths */
  310.       /* that are not multiples of 4 won't become too long.           */
  311.       if (bytecount == 5)
  312.       {
  313.         fputc(ch1, outfile);
  314.         fputc(ch2, outfile);
  315.         fputc(ch3, outfile);
  316.         fputc(ch4, outfile);
  317.  
  318.         bytecount = 0;
  319.       }
  320.  
  321.       if (new_version)
  322.         calcchecksum(ch);
  323.  
  324.       if (((BYTE)ch >= '!') && ((BYTE)ch < ('!' + 85)))  /* Valid characters. */
  325.       {
  326.         /* See if we can take all 5 bytes and decode them right away. */
  327.         /* That is, if all remaining bytes are on the current line.   */
  328.         if (length >= 4 - bytecount)
  329.         {
  330.           length -= 4 - bytecount;
  331.  
  332.           if (bytecount == 0)
  333.             codeword = DECODE(ch);
  334.           else
  335.             codeword = codeword * 85 + DECODE(ch);
  336.  
  337.           for (bytecount++; bytecount < 5; bytecount++)
  338.           {
  339.             ch = *buffer++;
  340.             if (new_version)
  341.               calcchecksum(ch);
  342.             codeword = codeword * 85 + DECODE(ch);
  343.           }
  344.         }
  345.         else
  346.         {
  347.           /* Shift codeword and insert character. */
  348.  
  349.           if (bytecount == 0)
  350.           {
  351.             codeword = DECODE(ch);
  352.             bytecount = 1;
  353.           } 
  354.           else /* bytecount < 5 */
  355.           {
  356.             codeword = codeword * 85 + DECODE(ch);
  357.             bytecount ++;
  358.           }
  359.         }
  360.  
  361.         if (bytecount == 5)
  362.         {
  363.           tmp_codeword = codeword;
  364.  
  365.           ch4 = (int)tmp_codeword & 0xFF;
  366.           ch3 = (int)(tmp_codeword >>= 8) & 0xFF;
  367.           ch2 = (int)(tmp_codeword >>= 8) & 0xFF;
  368.           ch1 = (int)(tmp_codeword >> 8) & 0xFF;
  369.  
  370.           if (!new_version)
  371.           {
  372.             calcchecksum(ch1);
  373.             calcchecksum(ch2);
  374.             calcchecksum(ch3);
  375.             calcchecksum(ch4);
  376.           }
  377.         }
  378.       }
  379.       else if ((BYTE)ch == 'z' || (new_version && (BYTE)ch == 'y'))
  380.       {
  381.         if (bytecount != 0)
  382.           error = TRUE;
  383.         else
  384.         {
  385.           ch1 = ch2 = ch3 = ch4 = (ch == 'z') ? 0 : ' ';
  386.           if (!new_version)
  387.           {
  388.             calcchecksum(ch1);
  389.             calcchecksum(ch1);
  390.             calcchecksum(ch1);
  391.             calcchecksum(ch1);
  392.           }
  393.           bytecount = 5;
  394.         }
  395.       }
  396.       else
  397.         error = TRUE;
  398.     }
  399.   }
  400.  
  401.   return(error);
  402. }
  403.